package edu.uct.tamnd.viettourism.atm;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter;
import com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;

import edu.uct.tamnd.viettourism.MainActivity;
import edu.uct.tamnd.viettourism.R;
import edu.uct.tamnd.viettourism.helper.DatabaseHelper;
import edu.uct.tamnd.viettourism.maps.JSONParser;

public class MapsATM extends FragmentActivity implements LocationListener{

	private GoogleMap mMap;
	private Location location;
	private DatabaseHelper mHelper;
	
	ArrayList<ATMItem> placesMarker;
	private String TAG = "Maps ATM";
	private String choose;
	
	private Marker mMarkers;
	private Marker currentMarker;
	private String bankName;
	private String id;
	private String latitude;
	private String longitude;
	private String bankID;
	private LatLngBounds bounds;
	
	@Override
	protected void onCreate(Bundle arg0) {
		// TODO Auto-generated method stub
		super.onCreate(arg0);
		setContentView(R.layout.maps);
		openDatabase();
		createAlertDialog();
		createCurrentPlacesMarker();
		//currentMarker.showInfoWindow();
		
		mMap.setInfoWindowAdapter(new InfoWindowAdapter() {
			
			@Override
			public View getInfoWindow(Marker marker) {
				// TODO Auto-generated method stub
				return null;
			}
			
			@Override
			public View getInfoContents(Marker marker) {
				// TODO Auto-generated method stub
				View v = getLayoutInflater().inflate(R.layout.custom_marker_atm, null);
	        	Log.d("Marker", "ID != 0");
	        	Cursor cursor = mHelper.readATM(marker.getTitle());
				
				if (cursor.moveToFirst()) {
					do {
						String mBankID = cursor.getString(cursor.getColumnIndex(TableNameATM.COLUMN_BANK_ID));
						String mAddress = cursor.getString(cursor.getColumnIndex(TableNameATM.COLUMN_ADDRESS));
						String mLat = cursor.getString(cursor.getColumnIndex(TableNameATM.COLUMN_LAT));
						String mLng = cursor.getString(cursor.getColumnIndex(TableNameATM.COLUMN_LONG));
						
						Cursor c = mHelper.readBank(mBankID);
						if (c.moveToFirst()) {
							do{
								String bankName = c.getString(c.getColumnIndex(TableNameBank.COLUMN_NAME));
								try {
									Log.d(TAG, "ID marker = " + marker.getTitle());
				    	        	Log.d(TAG, "set data to marker");
				    	        	
				    	        	TextView tvBankNameMarker = (TextView) v.findViewById(R.id.tvBankName);
				    	        	tvBankNameMarker.setText(bankName);
				    	        	
				    	        	TextView tvAddressBankMarker = (TextView) v.findViewById(R.id.tvATMAddress);
				    	        	tvAddressBankMarker.setText(mAddress);
				    	        	
				    			} catch (Exception e) {
				    				Log.d(TAG, "Set data error");
				    			}
	
							}while (cursor.moveToNext());
						}
										
					} while (cursor.moveToNext());
				}

	        
	        
	        // Returning the view containing InfoWindow contents
	        return v;
			}
		});
		
		mMap.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
			
			private LatLngBounds boundRoute;

			@Override
			public void onInfoWindowClick(Marker marker) {
				// TODO Auto-generated method stub
				mMap.clear();
				LatLngBounds.Builder builderRoute = new LatLngBounds.Builder();
				createCurrentPlacesMarker();
				currentMarker.hideInfoWindow();
				marker.showInfoWindow();
				
				builderRoute.include(currentMarker.getPosition());
				Log.d(TAG, "Marker ID Clicked = " + marker.getTitle());
				
				if(Integer.parseInt(marker.getTitle()) == 0){
					createAlertDialog();
	    		}else{
	    			createPlacesMarker(choose);
					String url = makeURL(location.getLatitude(), location.getLongitude(), marker.getPosition().latitude, marker.getPosition().longitude);
		    		Log.d("MapsView", "url = "+url);
		    		connectAsyncTask cnt = new connectAsyncTask(url);
		    		cnt.execute(url);
		    		
		    		marker.showInfoWindow();
		    		builderRoute.include(marker.getPosition());
					boundRoute = builderRoute.build();
					
					int padding = 150; // offset from edges of the map in pixels
					CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(boundRoute, padding);
		    		mMap.animateCamera(cu);
	    		}
				
			}
		});
	}

	public String makeURL (double sourcelat, double sourcelog, double destlat, double destlog ){
        StringBuilder urlString = new StringBuilder();
        urlString.append("http://maps.googleapis.com/maps/api/directions/json");
        urlString.append("?origin=");// from
        urlString.append(Double.toString(sourcelat));
        urlString.append(",");
        urlString.append(Double.toString( sourcelog));
        urlString.append("&destination=");// to
        urlString.append(Double.toString( destlat));
        urlString.append(",");
        urlString.append(Double.toString( destlog));
        urlString.append("&sensor=false&mode=driving&alternatives=true");
        return urlString.toString();
	}

	public void drawPath(String result) {

	    try {
	            //Tranform the string into a json object
	           final JSONObject json = new JSONObject(result);
	           JSONArray routeArray = json.getJSONArray("routes");
	           JSONObject routes = routeArray.getJSONObject(0);
	           JSONObject overviewPolylines = routes.getJSONObject("overview_polyline");
	           String encodedString = overviewPolylines.getString("points");
	           List<LatLng> list = decodePoly(encodedString);

	           for(int z = 0; z<list.size()-1;z++){
	                LatLng src= list.get(z);
	                LatLng dest= list.get(z+1);
	                Polyline line = mMap.addPolyline(new PolylineOptions()
	                .add(new LatLng(src.latitude, src.longitude), new LatLng(dest.latitude, dest.longitude))
	                .width(4)
	                .color(Color.BLUE)
	                .geodesic(true));
	                
	            }

	    } 
	    catch (JSONException e) {

	    }
	} 
	private List<LatLng> decodePoly(String encoded) {

	    List<LatLng> poly = new ArrayList<LatLng>();
	    int index = 0, len = encoded.length();
	    int lat = 0, lng = 0;

	    while (index < len) {
	        int b, shift = 0, result = 0;
	        do {
	            b = encoded.charAt(index++) - 63;
	            result |= (b & 0x1f) << shift;
	            shift += 5;
	        } while (b >= 0x20);
	        int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
	        lat += dlat;

	        shift = 0;
	        result = 0;
	        do {
	            b = encoded.charAt(index++) - 63;
	            result |= (b & 0x1f) << shift;
	            shift += 5;
	        } while (b >= 0x20);
	        int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
	        lng += dlng;

	        LatLng p = new LatLng( (((double) lat / 1E5)),
	                 (((double) lng / 1E5) ));
	        poly.add(p);
	    }

	    return poly;
	}

	private class connectAsyncTask extends AsyncTask<String, Void, String>{
	    private ProgressDialog progressDialog;
	    String url;
	    connectAsyncTask(String urlPass){
	        url = urlPass;
	    }
	    @Override
	    protected void onPreExecute() {
	        // TODO Auto-generated method stub
	        super.onPreExecute();
	        progressDialog = new ProgressDialog(MapsATM.this);
	        progressDialog.setMessage("Đang tìm đường, vui lòng đợi...");
	        progressDialog.setIndeterminate(true);
	        progressDialog.show();
	    }
	    @Override
	    protected String doInBackground(String... params) {
	        JSONParser jParser = new JSONParser();
	        String json = jParser.getJSONFromUrl(url);
	        Log.d("background", "Da lay json = "+json);
	        return json;
	    }
	    @Override
	    protected void onPostExecute(String result) {
	        super.onPostExecute(result);   
	        progressDialog.hide();        
	        if(result!=null){
	        	Log.d("PostExecute json = ", result);
	            drawPath(result);
	        }
	    }
	    
	}
	
	private void createAlertDialog() {
		// TODO Auto-generated method stub
		final CharSequence[] menu = {"Tất cả", "VietcomBank", "TechcomBank", "Agribank", "ACB", "VietinBank", "DongA Bank", "Ocean Bank", "BIDV"};
		AlertDialog.Builder alt = new AlertDialog.Builder(this);
		alt.setIcon(R.drawable.poi_search);
		alt.setTitle("Chọn ngân hàng cần tra cứu");
		
//		ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_single_choice);
//		adapter.add("Tất cả");
//		Cursor cursor = mHelper.readBank();
//		if (cursor.moveToFirst()) {
//			do {
//				String bankID = cursor.getString(cursor.getColumnIndex(TableNameBank.COLUMN_ID));
//				String bankName = cursor.getString(cursor.getColumnIndex(TableNameBank.COLUMN_NAME));
//				adapter.add(bankName);
//
//			} while (cursor.moveToNext());
//			
//		}
		alt.setSingleChoiceItems(menu, -1, new OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int item) {
				// TODO Auto-generated method stub
				switch (item) {
				case 0:
					createPlacesMarker("0");
					choose = "0";
					dialog.dismiss();
					break;
				case 1:
					createPlacesMarker("1");
					choose = "1";
					dialog.dismiss();
					break;
				case 2:
					createPlacesMarker("2");
					choose = "2";
					dialog.dismiss();
					break;
				case 3:
					createPlacesMarker("3");
					choose = "3";
					dialog.dismiss();
					break;
				case 4:
					createPlacesMarker("4");
					choose = "4";
					dialog.dismiss();
					break;
				case 5:
					createPlacesMarker("5");
					choose = "5";
					dialog.dismiss();
					break;
				case 6:
					createPlacesMarker("6");
					choose = "6";
					dialog.dismiss();
					break;
				case 7:
					createPlacesMarker("7");
					choose = "7";
					dialog.dismiss();
					break;
				case 8:
					createPlacesMarker("8");
					choose = "8";
					dialog.dismiss();
					break;
				default:
					break;
				}
			}
		});
		AlertDialog alert = alt.create();
		alert.show();
		
	}
	
	
	private void createCurrentPlacesMarker(){
		int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getBaseContext());
        if(status!=ConnectionResult.SUCCESS){ // Google Play Services are not available
        	
            int requestCode = 10;
            Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, this, requestCode);
            dialog.show();
 
        }else { // Google Play Services are available
 
            // Getting reference to the SupportMapFragment of activity_main.xml
            SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
 
            // Getting GoogleMap object from the fragment
            mMap = fm.getMap();
            
            // Enabling MyLocation Layer of Google Map
            mMap.setMyLocationEnabled(true);
            try {
                // Getting LocationManager object from System Service LOCATION_SERVICE
                LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
     
                // Creating a criteria object to retrieve provider
                Criteria criteria = new Criteria();
     
                // Getting the name of the best provider
                String provider = locationManager.getBestProvider(criteria, true);
     
                // Getting Current Location
                location = locationManager.getLastKnownLocation(provider);
     
                if(location!=null){
                    onLocationChanged(location);
                }
                locationManager.requestLocationUpdates(provider, 20000, 0, this);
                LatLng currentPoint = new LatLng(location.getLatitude(), location.getLongitude());
                
                mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(currentPoint, 12));

                currentMarker = mMap.addMarker(new MarkerOptions()
                		.position(currentPoint)
                		.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_from_1))
                		.snippet("Bạn đang đứng ở đây.\n Chọn để tìm máy ATM gần nhất"));
                currentMarker.setTitle("0");
                Log.d("Create Current Marker", "Da set title cho current Marker, title = " + currentMarker.getTitle());
                currentMarker.showInfoWindow();
			} catch (Exception e) {
				Toast.makeText(MapsATM.this, "Lỗi tìm kiếm nhà cung cấp dịch vụ", Toast.LENGTH_SHORT).show();
				Intent i = new Intent(MapsATM.this, MainActivity.class);
				startActivity(i);
			}
	
            
        }
	}
	
	private void createPlacesMarker(String bID) {
		// TODO Auto-generated method stub
		mMap.clear();
		LatLngBounds.Builder builder = new LatLngBounds.Builder();
		createCurrentPlacesMarker();
		builder.include(currentMarker.getPosition());
		Log.d(TAG, "Nhan bankID = " + bID);
		Cursor cursor;
		if(bID == "0"){
			cursor = mHelper.readPlacesATM();
		}
		else{
			cursor = mHelper.readPlacesATM(bID);
		}
		Log.d(TAG, "Lay Cursor thanh cong");
		if (cursor.moveToFirst()) {
			do {
				id = cursor.getString(cursor.getColumnIndex(TableNameATM.COLUMN_ID));
				bankID = cursor.getString(cursor.getColumnIndex(TableNameATM.COLUMN_BANK_ID));
				latitude = cursor.getString(cursor.getColumnIndex(TableNameATM.COLUMN_LAT));
				longitude = cursor.getString(cursor.getColumnIndex(TableNameATM.COLUMN_LONG));
				
				Location placesLocation = new Location(id);
				double lat = 0.0;
				double lng = 0.0;
					
				lat = Double.parseDouble(latitude.trim());
				lng = Double.parseDouble(longitude.trim());
			
				placesLocation.setLatitude(lat);
				placesLocation.setLongitude(lng);
				double distance = location.distanceTo(placesLocation);
				try {
					if(distance <= 10000 && bID == "0"){
						LatLng point = new LatLng(placesLocation.getLatitude(), placesLocation.getLongitude());
						Log.d(TAG, "ID = "+ id + "\tDistance = " + distance + "\tLatLng = " + point.latitude + " " + point.longitude);
						createMarkerOnMaps(point, id);
						builder.include(point);
						bounds = builder.build();
					}else{
						if(distance <= 10000 && Integer.parseInt(bID) == Integer.parseInt(bankID)){
							LatLng point = new LatLng(placesLocation.getLatitude(), placesLocation.getLongitude());
							Log.d(TAG, "ID = "+ id + "\tDistance = " + distance + "\tLatLng = " + point.latitude + " " + point.longitude);
							createMarkerOnMaps(point, id);
							builder.include(point);
							bounds = builder.build();
						}
					}	
				} catch (Exception e) {
					Toast.makeText(MapsATM.this, "Không có ATM nào trong khoảng cách 10km", Toast.LENGTH_SHORT).show();
				}

			} while (cursor.moveToNext());
			
		}
		int padding = 80; // offset from edges of the map in pixels
		CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
		mMap.animateCamera(cu);
	}
	
	
	private void createMarkerOnMaps(LatLng point, String id) {
		// TODO Auto-generated method stub
//		mMap.clear();
		
        // Creating an instance of MarkerOptions to set position
        MarkerOptions markerOptions = new MarkerOptions();

        // Setting position on the MarkerOptions
        markerOptions.position(point);
        
        //Setting icon to marker
        markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_from));
        
        // Animating to the currently position
//        mMap.animateCamera(CameraUpdateFactory.newLatLng(point));

        // Adding marker on the GoogleMap
        mMarkers = mMap.addMarker(markerOptions);
        mMarkers.setTitle(id);
        Log.d(TAG, "da set id cho marker");
       
	}
	
	private void openDatabase() {
		// TODO Auto-generated method stub
		mHelper = new DatabaseHelper(this);
		try {
			mHelper.createDatabase();
			Log.d(TAG , "Đã gọi hàm create");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			Log.d("CityList", e.getMessage());
			Toast.makeText(this, "Lỗi db", Toast.LENGTH_LONG).show();
		}
	}

	@Override
	public void onLocationChanged(Location arg0) {
		// TODO Auto-generated method stub
		double latitude = location.getLatitude();
        double longitude = location.getLongitude();
        //LatLng latLng = new LatLng(latitude, longitude);
	}

	@Override
	public void onProviderDisabled(String arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onProviderEnabled(String arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
		getMenuInflater().inflate(R.menu.atm_option_menu, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// TODO Auto-generated method stub
		switch (item.getItemId()) {
	      case R.id.satellite:
	            mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
	            return true;
	      case R.id.traffic:
	            mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
	            return true;
	      case R.id.local:
	    	  createAlertDialog();
//	    	  	createAlertDialog();
	    	  	return true;
	      default:
	            return super.onOptionsItemSelected(item);
		}
	}
}